/**
 * <AiRmob-Framework; A simple augmented reality framework for android >
    Copyright (C) <2012>  <AiRmob Team>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package rendercomponents;

import android.opengl.Matrix;

public class Parent extends Object {

	protected float[] mTransformationMatrix;
	protected Parent parent;
	protected int colorID;
	protected int oldColorID = -1;

	// Stores the accumulated values for all scales
	// used for setRotation in the techdemo
	// If the transformation-matrix is changed manually this value may be
	// incorrect.
	protected float[] scaleSum = { 1.0f, 1.0f, 1.0f };

	public boolean isVisible = true;

	protected Parent(Parent parent) {
		this.mTransformationMatrix = new float[16];
		Matrix.setIdentityM(mTransformationMatrix, 0);
		this.parent = parent;
	}

	/**
	 * The parent has to be append to a scene for this method to work.
	 * 
	 * @return the scene to which this parent is appended.
	 */
	public Scene getScene() {
		if (this.type != 0) {
			return this.parent.getScene();
		} else {
			return (Scene) this;
		}
	}

	protected void changed() {
		this.getScene().somethingChanged = true;
	}

	// ////////////////////////////////////////////////////////
	// /Functions for transformations
	// ////////////////////////////////////////////////////////

	/**
	 * Sets the transformation-matrix of this parent to identity.
	 */
	public void setTransformationToIdentity() {
		Matrix.setIdentityM(this.mTransformationMatrix, 0);

		this.changed();
	}

	/**
	 * Rotates this parent (and therefore its child/children) around the X-Axis.
	 * 
	 * @param angle
	 */
	public void rotateX(float angle) {
		float[] matrix = new float[16];
		Matrix.setIdentityM(matrix, 0);
		Matrix.rotateM(matrix, 0, angle, 1, 0, 0);
		Matrix.multiplyMM(this.mTransformationMatrix, 0, matrix, 0,
				this.mTransformationMatrix, 0);

		this.changed();
	}

	/**
	 * Rotates this parent (and therefore its child/children) around the Y-Axis.
	 * 
	 * @param angle
	 */
	public void rotateY(float angle) {
		float[] matrix = new float[16];
		Matrix.setIdentityM(matrix, 0);
		Matrix.rotateM(matrix, 0, angle, 0, 1, 0);
		Matrix.multiplyMM(this.mTransformationMatrix, 0, matrix, 0,
				this.mTransformationMatrix, 0);

		this.changed();
	}

	/**
	 * Rotates this parent (and therefore its child/children) around the Z-Axis.
	 * 
	 * @param angle
	 */
	public void rotateZ(float angle) {
		float[] matrix = new float[16];
		Matrix.setIdentityM(matrix, 0);
		Matrix.rotateM(matrix, 0, angle, 0, 0, 1);
		Matrix.multiplyMM(this.mTransformationMatrix, 0, matrix, 0,
				this.mTransformationMatrix, 0);

		this.changed();
	}

	/**
	 * Translates this parent (and therefore its child/children).
	 * 
	 * @param x
	 * @param y
	 * @param z
	 */
	public void translate(float x, float y, float z) {
		float[] matrix = new float[16];
		Matrix.setIdentityM(matrix, 0);
		Matrix.translateM(matrix, 0, x, y, z);
		Matrix.multiplyMM(this.mTransformationMatrix, 0, matrix, 0,
				this.mTransformationMatrix, 0);

		this.changed();
	}

	/**
	 * Scales this parent (and therefore its child/children).
	 * 
	 * @param x
	 * @param y
	 * @param z
	 */
	public void scale(float x, float y, float z) {
		float[] matrix = new float[16];
		Matrix.setIdentityM(matrix, 0);
		Matrix.scaleM(matrix, 0, x, y, z);
		Matrix.multiplyMM(this.mTransformationMatrix, 0, matrix, 0,
				this.mTransformationMatrix, 0);
		this.scaleSum[0] *= x;
		this.scaleSum[1] *= y;
		this.scaleSum[2] *= z;
		this.changed();
	}

	/**
	 * 
	 * Rotates this parent (and therefore its child/children).
	 * 
	 * @param angle
	 * @param x
	 * @param y
	 * @param z
	 */
	public void rotate(float angle, float x, float y, float z) {
		float[] matrix = new float[16];
		Matrix.setIdentityM(matrix, 0);
		Matrix.rotateM(matrix, 0, angle, x, y, z);
		Matrix.multiplyMM(this.mTransformationMatrix, 0, matrix, 0,
				this.mTransformationMatrix, 0);

		this.changed();
	}

	/**
	 * 
	 * @return the transformation-matrix of this parent
	 */
	public float[] getTransformationMatrix() {
		return this.mTransformationMatrix;
	}

	/**
	 * Deactivates picking for this parent. Picking itself stays activated for
	 * all other parents.
	 */
	public void deactivatePicking() {
		if (this.colorID != -1) {
			this.oldColorID = this.colorID;
			this.colorID = -1;
		}
	}

	/**
	 * Reactivates picking for this parent if deactivated. Picking itself has to
	 * be activated in the settings before starting the renderer.
	 */
	public void activatePicking() {
		if (this.oldColorID != -1)
			this.colorID = this.oldColorID;
	}

	/**
	 * 
	 * If the transformation-matrix is changed manually this value may be
	 * incorrect.
	 * 
	 * @return the sum of all so far accumulated scale-operations as a float[3]
	 *         (x/y/z)
	 */
	public float[] getScaleSum() {
		return this.scaleSum;
	}

}
